#import <appkit/appkit.h>
#import "CustomVideoView.h"
#import <dpsclient/event.h>
#import <dpsclient/psops.h>
#import <dpsclient/wraps.h>
#import <sys/param.h>
#import <stdio.h>
#import <strings.h>

@implementation CustomVideoView

- initFrame:(const NXRect *)theFrame
{
  [super initFrame:theFrame];
// Get it to allocate the NXImage ahead of time so it will stop fast.
  [self setGrabOnStop:YES];
  theMode = NX_FROMINPUT;
  actualSize = YES;
  theImage = [NXImage findImageNamed:"AppIcon"];
  [theImage setScalable:YES];
  [theImage getSize:&imageSize];
  imagePoint.x = bounds.origin.x + (bounds.size.width - imageSize.width)/2.0;
  imagePoint.y = bounds.origin.y + (bounds.size.height-imageSize.height)/2.0;
  changed = YES;
  return self;
}

- mouseDown:(NXEvent *)theEvent
{
  NXEvent anEvent = *theEvent;
  NXPoint point1 = theEvent->location,point2;
  int oldMask;
  BOOL dragged = NO;
  
  oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
  if(theMode==NX_FROMINPUT)
  {
    // Set Grab rectangle.
    while(anEvent.type!=NX_MOUSEUP)
    {
      NXGetOrPeekEvent(DPSGetCurrentContext(),
        &anEvent, NX_MOUSEUPMASK|NX_LMOUSEDRAGGEDMASK,NX_FOREVER,10,0);
      if(anEvent.type==NX_MOUSEDRAGGED)
      {
        dragged = YES;
        point2 = anEvent.location;
        if(point1.x<point2.x)
          {grabRect.origin.x=point1.x;grabRect.size.width=point2.x - point1.x;}
        else
          {grabRect.origin.x=point2.x;grabRect.size.width=point1.x - point2.x;}
        if(point1.y<point2.y)
        {
          grabRect.origin.y=point1.y;
	grabRect.size.height=point2.y - point1.y;
        }
        else
        {
          grabRect.origin.y=point2.y;
	grabRect.size.height=point1.y - point2.y;
        }
        [self display];
      }
  
    }
    if(!dragged) grabRect.size.width = 0;
    [self display];
  }
  else
  {
    float dx=0,dy=0;
    if(actualSize)		// Move Image around
    {
      NXRect imageFrame,oldFrame;
      imageFrame.origin = imagePoint;imageFrame.size = imageSize;
      oldFrame = imageFrame;
      if(NXMouseInRect(&theEvent->location,&imageFrame,NO))
      {
        dx = theEvent->location.x - imagePoint.x;
        dy = theEvent->location.y - imagePoint.y;
        while(anEvent.type!=NX_MOUSEUP)
        {
          NXGetOrPeekEvent(DPSGetCurrentContext(),&anEvent,
	  NX_MOUSEUPMASK|NX_LMOUSEDRAGGEDMASK,NX_FOREVER,10,0);
          if(anEvent.type==NX_MOUSEDRAGGED)
          {
	  imagePoint.x = anEvent.location.x -dx;
	  imagePoint.y = anEvent.location.y -dy;
	  imageFrame.origin = imagePoint;
	  NXUnionRect(&imageFrame,&oldFrame);
            [self display:&oldFrame :1];
          }
        }
      }
    }
  }
  [window setEventMask:oldMask];
  return self;
}

- grab:sender
{
  id bitmap;
  id image;

  // Read the bits from the window
  image = [self grab];
  [image lockFocus];
  bitmap = [[NXBitmapImageRep alloc] initData:NULL fromRect:(grabRect.size.width == 0) ? &bounds : &grabRect];
  [image unlockFocus];
  if (bitmap)
  {
    id mySavePanel = [SavePanel new];
    char filename[MAXPATHLEN+1];
    [mySavePanel runModal];
    if([mySavePanel filename])
    {
      NXStream *s = NXOpenMemory (NULL, 0, NX_READWRITE);
      strcpy(filename,[mySavePanel filename]);
      if(strcmp(&filename[strlen(filename)-5],".tiff"))
        strcat(filename,".tiff");
      if (s)
      {
        [bitmap writeTIFF:s usingCompression:NX_TIFF_COMPRESSION_JPEG
                            andFactor:10];
        NXFlush (s);
        if (NXSaveToFile (s, filename))
          NXRunAlertPanel("Error Saving File","Filename: %s","OK",
	NULL,NULL,filename);
        NXCloseMemory (s, NX_FREEBUFFER);
      }
    }
    [bitmap free];
  }
  return self;
}

- setImage:sender
{
  // Set the graphic for output mode.
  id myOpenPanel = [OpenPanel new];
  
  if([myOpenPanel runModalForTypes:[NXImage imageFileTypes]])
  {
    const char *theFileName = [myOpenPanel filename];
    
    if(theImage) [theImage free];
    theImage = [[NXImage alloc] initFromFile:theFileName];
    [theImage setScalable:YES];
    [theImage getSize:&imageSize];
    imagePoint.x = bounds.origin.x + (bounds.size.width - imageSize.width)/2.0;
    imagePoint.y = bounds.origin.y + (bounds.size.height-imageSize.height)/2.0;
    changed = YES;
  }
  [self display];
  return self;
}

- drawSelf:(const NXRect *)rects :(int)rectCount
{
  if(theMode==NX_FROMVIEW)
  {
    NXRectClip(rects);
    NXEraseRect(&rects[0]);
    if(!theImage) return self;
    if(actualSize)
    {
      if(changed) {[theImage setSize:&imageSize];changed = NO;}
      [theImage composite:NX_SOVER toPoint:&imagePoint];
    }
    else
    {
      if(changed) {[theImage setSize:&bounds.size];changed = NO;}
      [theImage composite:NX_SOVER toPoint:&bounds.origin];
    }
  }
  else
  {
   [super drawSelf:rects :rectCount];
   PSsetgray(NX_WHITE);
   PSsetalpha(1.0);
   if(grabRect.size.width!=0) NXFrameRect(&grabRect);
  }
  return self;
}

- setOutputMode:(int)mode
{
  theMode = mode;
  [super setOutputMode:mode];
  return self;
}

- setActualSize:sender
{
  actualSize = [[sender selectedCell] tag];
  changed = YES;
  [self display];
  return self;
}

- clear:sender
{
  if(theImage) [theImage free];
  theImage = NULL;
  [self display];
  return self;
}

@end
